#include "common.h"
#include "mail_type.h"
#include "control.h"
#include "PacketParser.h"
#include "global.h"
#include <libxml/parser.h>

int ControlC302;
char C302ServerIp[MAX_LENGTH];
int C302Serverport;

void * GetC302ServerInfo(void * block)
{
	while(1)
	{
		xmlDocPtr doc = NULL;
		xmlNodePtr curNode = NULL;
		xmlNodePtr itemNode = NULL;

		doc = xmlReadFile("/LzSystem/C302Device.xml", "UTF-8", XML_PARSE_RECOVER);
		if (!doc) 
		{
			fprintf(stderr, "Read C302 configure file failed!\n");
			return;
		}
		curNode = xmlDocGetRootElement(doc);
		if (!curNode)
		{
			fprintf(stderr, "Empty C302 configure file!\n");
			xmlFreeDoc(doc);
			return;
		}
		if (xmlStrcmp(curNode->name, BAD_CAST "C302Device"))
		{
			fprintf(stderr, "Root node error!\n");
			xmlFreeDoc(doc);
			return;
		}
		itemNode = curNode->xmlChildrenNode;
		while (itemNode)
		{
			if (itemNode->type != XML_ELEMENT_NODE)
			{
				itemNode = itemNode->next;
				continue;
			}
			if (!xmlStrcmp(itemNode->name, BAD_CAST "Control"))
			{
				ControlC302 = atoi((const char *)xmlNodeGetContent(itemNode));
			} 
			else if (!xmlStrcmp(itemNode->name, BAD_CAST "ServerIp"))
			{
				memset(C302ServerIp, 0, MAX_LENGTH);
				memcpy(C302ServerIp, (const char *)xmlNodeGetContent(itemNode), strlen((const char *)xmlNodeGetContent(itemNode)));
			} 
			else if (!xmlStrcmp(itemNode->name, BAD_CAST "ServerPort"))
			{
				C302Serverport = atoi((const char *)xmlNodeGetContent(itemNode));
			}
			itemNode = itemNode->next;
		}
		xmlFreeDoc(doc);
		
		sleep(30);
	}
}

int init()
{
	mail_tab.head = (Mail_info *)malloc(sizeof(Mail_info));
	if (mail_tab.head == NULL)
	{
		perror("webmail:init()->malloc()1");
		return -1;
	}
	mail_tab.head->next = NULL;
	mail_tab.head->prev = NULL;
	mail_tab.count = 0;

	attach_tab.head = (Attach_info *)malloc(sizeof(Attach_info));
	if (attach_tab.head == NULL) 
	{
		perror("webmail:init()->malloc()2");
		return -1;
	}
	attach_tab.head->next = NULL;
	attach_tab.head->prev = NULL;
	attach_tab.tail = attach_tab.head;
	attach_tab.count = 0;

	if(lzDataPath == NULL)
	{
		strcpy(mail_data_path, "/home/LzData/moduleData/webmail");   //发送接受的邮件存放路径
		strcpy(mail_temp_path, "/home/LzData/moduleData/webmail/temp");//附件上传的临时路径
		strcpy(attach_down_path, "/home/LzData/moduleData/webmail/downattach");//附件下载存放路径
		strcpy(mail_password_path,"/home/LzData/moduleData/webmail/loginpasswd");
	}
	else
	{
		strcpy(mail_data_path, lzDataPath);
		strcat(mail_data_path, "/LzData/moduleData/webmail");
		
		strcpy(mail_temp_path, lzDataPath);
		strcat(mail_temp_path, "/LzData/moduleData/webmail/temp");
		
		strcpy(attach_down_path, lzDataPath);
		strcat(attach_down_path, "/LzData/moduleData/webmail/downattach");
		
		strcpy(mail_password_path, lzDataPath);
		strcat(mail_password_path, "/LzData/moduleData/webmail/loginpasswd");
	}
	//创建目录
	mode_t dir_mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
	mkdir(mail_data_path, dir_mode);
	mkdir(mail_temp_path, dir_mode);
	mkdir(attach_down_path, dir_mode);
	mkdir(mail_password_path, dir_mode);
	
	pthread_t Thread_id;
	pthread_create(&Thread_id, NULL, GetC302ServerInfo, NULL);

	return 0;
}

/* webmail */
int analyse_webmail(struct PacketInfo * packetinfo)//return 0:webmail not do ; return 1:webmail do
{
	Mail_info *mail_info = NULL;
	Attach_info *attach_info = NULL;
	static int init_flag = 0;
	int is_to_s, m_or_a, result;
	unsigned short type, tmp_type;
	void *node;

	if (!init_flag) 
	{
		result = init();
		if (result == -1)
			return 0;
		init_flag = 1;
	}

	if(!g_status)
	{
		return 0;
	}

	if( packetinfo->pktType != TCP || (packetinfo->srcPort != 80 && packetinfo->destPort != 80 && packetinfo->srcPort != 8080 && packetinfo->destPort != 8080))
	{
		return 0;
	}

	if (!packetinfo->bodyLen && !packetinfo->tcp->fin && !packetinfo->tcp->rst)
	{
		return 0;
	}

	unsigned short packet_type = mail_type(packetinfo->body);

	mail_info = find_mail_node(packetinfo->ip->saddr, packetinfo->ip->daddr, packetinfo->tcp->source, packetinfo->tcp->dest, &is_to_s);
	if (mail_info != NULL)
	{
		
		if (packetinfo->tcp->rst == 1)
		{
			delete(mail_info);
			return 1;
		}
		m_or_a = 0;
		node = mail_info;
		type = mail_info->mail_type;
		mail_info->count = 0;
	}
	else
	{
		attach_info = find_attach_node(packetinfo->ip->saddr, packetinfo->ip->daddr, packetinfo->tcp->source, packetinfo->tcp->dest, &is_to_s, packet_type);
		if (attach_info != NULL)
		{
			
			if (packetinfo->tcp->rst == 1) 
			{
				if (attach_info->path_of_here[0] != 0)
					unlink(attach_info->path_of_here);
				del_attach_node(attach_info);
				delete_attach(attach_info);
				return 1;
			}
			m_or_a = 1;
			node = attach_info;
			type = attach_info->attach_type;
		}
	}

	if (mail_info == NULL && attach_info == NULL) 
	{
		type = packet_type;
		if (type <= 0) 
		{
			return 0;
		}

		tmp_type = type & 0X00FF;
		if(tmp_type <= 0x50 ||tmp_type >=0x80)
		{
			Mail_info *mail_info = insert_mail_node(packetinfo->srcMac,packetinfo->ip, packetinfo->tcp, type);
			if (mail_info == NULL)
				return 0;
			m_or_a = 0;
			is_to_s = 1;
			node = mail_info;
		} 
		else
		{
			Attach_info *attach_info = insert_attach_node(packetinfo->ip, packetinfo->tcp, type, packet_type);
			if (attach_info == NULL)
				return 0;
			m_or_a = 1;
			is_to_s = 1;
			node = attach_info;
		}
	}

	tmp_type = type >> 8;
	switch (tmp_type) {
	case 1:
		analyse_sina(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 2:
		analyse_21cn(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 3:
		analyse_sohu(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 4:
		analyse_163(packetinfo,node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 5:
		analyse_hotmail(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 6:
		analyse_yahoo(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 7:
		analyse_tom(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 8:
		analyse_yeah(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 9:
		analyse_eyou(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x0A:
		analyse_263(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x0B:
		analyse_qq(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x0C:
		analyse_sogou(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x0D:
		analyse_126(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x0E:
		analyse_188(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x0F:
		analyse_gmail(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x10:
		analyse_mail(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x11:
		analyse_aol(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a, packetinfo->destMac);
		break;
	case 0x12:
		analyse_hanmail(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a, packetinfo->destMac);
		break;
	case 0x13:
		analyse_139(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;

	//手机webmail
	case 0x81:
		analyse_m_163(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	case 0x82:
		analyse_m_qq(node, packetinfo->body, packetinfo->bodyLen, packetinfo->tcp, is_to_s, m_or_a);
		break;
	}

	return 1;
}

/* test */
void web_test(void *header, const char *packet)
{
	struct ethhdr *peth;
	struct iphdr *pip;
	struct tcphdr *ptcp;
	Mail_info *mail_info = NULL;
	Attach_info *attach_info = NULL;
	char *ptemp, *data;
	unsigned int len;
	unsigned int data_len;
	static int init_flag = 0;
	int is_to_s, m_or_a, result;
	int ethprotol;
	unsigned short type, tmp_type;
	void *node;

	if (!init_flag) 
	{
		result = init();
		if (result == -1)
			return;
		init_flag = 1;
	}

	ptemp = (char *)packet;
	peth = (struct ethhdr *)ptemp;
	ptemp += sizeof(struct ethhdr);
	pip = (struct iphdr *)ptemp;
	ptemp += sizeof(struct iphdr);
	ptcp=(struct tcphdr *)ptemp;
	ethprotol = ntohs(peth->h_proto);
	if(ethprotol != 0x0800 || pip->protocol != IPPROTO_TCP || (ntohs(ptcp->dest) != 80 && ntohs(ptcp->source) != 80))
	{
		return ;
	}

	data = (char *)ptcp + 4 * ptcp->doff;
	data_len = ntohs(pip->tot_len) - 4 * pip->ihl - 4 * ptcp->doff;
	data[data_len] = 0;

	if (!data_len && !ptcp->fin && !ptcp->rst) 
	{
		return ;
	}
	
	unsigned short packet_type=mail_type(data);

	mail_info = find_mail_node(pip->saddr, pip->daddr, ptcp->source, ptcp->dest, &is_to_s);
	if (mail_info != NULL) 
	{
		//printf("\nis old mail node ...\n");
		//printf("%s\n",data);
		
		if (ptcp->rst == 1) 
		{
			delete(mail_info);
			return ;
		}
		
		m_or_a = 0;
		node = mail_info;
		type = mail_info->mail_type;
		mail_info->count = 0;
	} 
	else 
	{
		attach_info = find_attach_node(pip->saddr, pip->daddr, ptcp->source, ptcp->dest, &is_to_s, packet_type);
		if (attach_info != NULL) 
		{
			//printf("\nis old attach node ...\n");
			//printf("%s\n",data);
		
			if (ptcp->rst == 1) 
			{				
				if (attach_info->path_of_here[0] != 0)
					unlink(attach_info->path_of_here);
				del_attach_node(attach_info);
				delete_attach(attach_info);
				return ;
			}
			m_or_a = 1;
			node = attach_info;
			type = attach_info->attach_type;
		}
	}

	if (mail_info == NULL && attach_info == NULL) 
	{
		type = packet_type;
		if (type <= 0) 
		{
			return ;
		}

	    	tmp_type = type & 0X00FF;
		if(tmp_type <= 0x50) //mail
		{		
			//printf("\nis new mail node ...\n");
			//printf("%s\n",data);
		
			Mail_info *mail_info = insert_mail_node(peth->h_source, pip, ptcp, type);
			if (mail_info == NULL)
				return ;
			m_or_a = 0;
			is_to_s = 1;
			node = mail_info;
		} 
		else //attach
		{
			//printf("\nis new attach node ...\n");
			//printf("%s\n",data);
			
			Attach_info *attach_info = insert_attach_node(pip, ptcp, type, packet_type);
			if (attach_info == NULL)
				return ;
			m_or_a = 1;
			is_to_s = 1;
			node = attach_info;
		}
	}

	tmp_type = type >> 8;
	//data_len++;
	switch (tmp_type) 
	{
	case 1:
		analyse_sina(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 2:
		analyse_21cn(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 3:
		analyse_sohu(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 4:
		analyse_163(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 5:
		analyse_hotmail(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 6:
		analyse_yahoo(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 7:
		analyse_tom(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 8:
		analyse_yeah(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 9:
		analyse_eyou(node, data, data_len, ptcp, is_to_s, m_or_a);
		break;
	case 0x0A:
		analyse_263(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	case 0x0B:
		analyse_qq(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	case 0x0C:
		analyse_sogou(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	case 0x0D:
		analyse_126(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	case 0x0E:
		analyse_188(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	case 0x13:
		analyse_139(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;

	//手机webmail
	case 0x81:
		analyse_m_163(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	case 0x82:
		analyse_m_qq(node,data,data_len,ptcp,is_to_s,m_or_a);
		break;
	}
}

